TypeScript 93.3%
JavaScript 4.4%
CSS 2.3%
1/**2 * Author: Simon-Pierre Boucher3 * Contact: contact@spboucher.ai4 * Project: Hilmacorp.ai — Web Platform5 * File: app/[locale]/layout.tsx6 * Description: Locale-scoped root layout — HTML shell, fonts, global metadata, header and footer7 */89import type { Metadata } from "next";10import { Inter, Fraunces } from "next/font/google";11import { notFound } from "next/navigation";12import Header from "@/components/Header";13import Footer from "@/components/Footer";14import CookieConsent from "@/components/CookieConsent";15import { getMessages, isLocale, locales, type Locale } from "@/lib/i18n";16import "@/app/globals.css";1718const inter = Inter({ subsets: ["latin"], variable: "--font-inter", display: "swap" });19const fraunces = Fraunces({ subsets: ["latin"], variable: "--font-fraunces", display: "swap" });2021const SITE_URL = process.env.NEXT_PUBLIC_SITE_URL ?? "https://www.hilmacorp.ai";2223export function generateStaticParams() {24 return locales.map((locale) => ({ locale }));25}2627export async function generateMetadata({28 params,29}: {30 params: Promise<{ locale: string }>;31}): Promise<Metadata> {32 const { locale } = await params;33 if (!isLocale(locale)) return {};34 const messages = getMessages(locale);35 return {36 metadataBase: new URL(SITE_URL),37 title: {38 default: messages.meta.home.title,39 template: `%s — ${messages.meta.siteName}`,40 },41 description: messages.meta.home.description,42 alternates: {43 languages: { fr: "/fr", en: "/en" },44 },45 openGraph: {46 type: "website",47 siteName: messages.meta.siteName,48 locale: locale === "fr" ? "fr_CA" : "en_US",49 url: `${SITE_URL}/${locale}`,50 title: messages.meta.home.title,51 description: messages.meta.home.description,52 },53 twitter: {54 card: "summary",55 title: messages.meta.home.title,56 description: messages.meta.home.description,57 },58 robots: { index: true, follow: true },59 };60}6162export default async function LocaleLayout({63 children,64 params,65}: {66 children: React.ReactNode;67 params: Promise<{ locale: string }>;68}) {69 const { locale } = await params;70 if (!isLocale(locale)) notFound();71 const typedLocale = locale as Locale;72 const messages = getMessages(typedLocale);7374 return (75 <html lang={typedLocale} className={`${inter.variable} ${fraunces.variable}`}>76 <body className="flex min-h-screen flex-col font-sans">77 <Header locale={typedLocale} nav={messages.nav} />78 <main className="flex-1">{children}</main>79 <Footer locale={typedLocale} messages={messages} />80 <CookieConsent locale={typedLocale} strings={messages.cookies} />81 </body>82 </html>83 );84}85